// File: projectfile.cpp
//
// Author(s): Dana Burkart
//
// Description: Implements the ProjectFile class, which manages loading and
//              saving to .itp files.
//

#include "projectfile.h"

const int FORMAT_VERSION = 1;
const char* FORMAT_VERSION_STR = "0001";

/**
 * Initializes this ProjectFile with a default name (untitled.itp) and other
 * initial values.
 */
ProjectFile::ProjectFile() {
	_header.numMetaItems = 0;
	_header.numFiles = 0;
    strcpy(_header.projectName, "untitled.itp\0");
    _header.nill = 0xDEADBABA;
    strcpy(_header.info, "<< Iterate project file >>");
    strcpy(_header.version, FORMAT_VERSION_STR);
    _header.metaOffset = 0;
    _header.fileOffset = 0;
}

/**
 * Same as above except takes a projectName.
 *
 * @param *projectName file save the ProjectFile to
 */
ProjectFile::ProjectFile(const char *projectName) {
	_header.numMetaItems = 0;
	_header.numFiles = 0;
	strcpy(_header.projectName, projectName);
	_header.nill = 0xDEADBABA;
	strcpy(_header.info, "<< Iterate project file >>");
	strcpy(_header.version, FORMAT_VERSION_STR);
	_header.metaOffset = 0;
	_header.fileOffset = 0;
}

/**
 * Wrapper for the real save function
 */
void ProjectFile::save(void) {
    save(_header.projectName);
}

/**
 * Saves the ProjectFile to the specified filename.
 *
 * @param *filename file to save the ProjectFile to
 */
void ProjectFile::save(char *filename) {
    fstream file(filename, ios::out | ios::binary | ios::trunc);
    if (_header.numMetaItems > 0)
    	_header.fileOffset = sizeof(ITPMeta)*_header.numMetaItems;
    file.write(reinterpret_cast<char *>(&_header), sizeof(ITPHeader));
    for (int i = 0; i < _header.numMetaItems; i++)
        file.write(reinterpret_cast<char *>(&_metaItems[i]), 
        	sizeof(ITPMeta));
    for (int i = 0; i < _header.numFiles; i++) {
        file.write(reinterpret_cast<char *>(&_files[i]), sizeof(ITPFile));
    }
    file.close();
}

void ProjectFile::load(void) {
	_files.clear();
	load(_header.projectName);
}

/**
 * Loads the specified file into this ProjectFile.
 *
 * @param *filename file to load
 */
void ProjectFile::load(char *filename) {
	fstream file(filename, ios::binary | ios::in);
	file.read(reinterpret_cast<char *>(&_header), sizeof(ITPHeader));
	for (int i = 0; i < _header.numMetaItems; i++) {
		ITPMeta temp;
		file.read(reinterpret_cast<char *>(&temp), sizeof(ITPMeta));
		_metaItems.push_back(temp);
	}
	for (int i = 0; i < _header.numFiles; i++) {
		ITPFile temp;
		file.read(reinterpret_cast<char *>(&temp), sizeof(ITPFile));
		_files.push_back(temp);
	}
	file.close();
}

/**
 * Adds a meta item to the file.
 *
 * @param metaItem the meta item to add
 */
void ProjectFile::addMetaItem(const ITPMeta* metaItem) {
	_metaItems.push_back(*metaItem);
	_header.numMetaItems++;
}

/**
 * Adds a file to the project.
 *
 * @param path path to the file
 */
void ProjectFile::addFile(const char *path) {
	ITPFile temp;
	strcpy(temp.path, path);
	_files.push_back(temp);
	_header.numFiles++;
}

/**
 * Returns the name of the project (not the project's filename).
 *
 * @return name of the project
 */
const char *ProjectFile::name(void) const {
	return _header.projectName;
}

/**
 * Re-names the project (not the project's filename).
 *
 * @return new name of the project
 */
const char *ProjectFile::name(const char *projectName) {
	strcpy(_header.projectName, projectName);
	return _header.projectName;
}

/** 
 * Returns a string containing the filetype version
 *
 * @return string containing filetype version
 */
const char *ProjectFile::fileVersion(void) const {
	return _header.version;
}

/**
 * Returns the number of files in this project
 *
 * @return number of files in the project
 */
int ProjectFile::fileCount(void) const {
	return _header.numFiles;
}

/**
 * Returns a vector of the meta items for the project.
 *
 * @return a vector of meta items
 */
vector<ITPMeta> ProjectFile::metaItems(void) const {
	return _metaItems;
}

/**
 * Returns a vector of files that are contained in the project.
 *
 * @return a vector of files
 */
vector<ITPFile> ProjectFile::files(void) const {
	return _files;
}

void ProjectFile::print(void) const {
	cout << "Info: " << _header.info << " fileformat v" << _header.version 
	     << endl << "Name: " << _header.projectName << endl
		 << "# of source files: " << _header.numFiles << endl
		 << "Files: " << endl;
		 
	for (int i = 0; i < fileCount(); i++) {
		cout << "  " << files()[i].path << endl;
	}
}
